home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / LANG / PROLOG / HUMBOLT / HUMBOLTS / _files / _humboltsr / READ._c < prev    next >
Text File  |  1990-06-10  |  23KB  |  909 lines

  1. /***************************************************
  2. ****************************************************
  3. **                                                **
  4. **  HU-Prolog     Portable Interpreter System     **
  5. **                                                **
  6. **  Release 1.62   January  1990                  **
  7. **                                                **
  8. **  Authors:      C.Horn, M.Dziadzka, M.Horn      **
  9. **                                                **
  10. **  (C) 1989      Humboldt-University             **
  11. **                Department of Mathematics       **
  12. **                GDR 1086 Berlin, P.O.Box 1297   **
  13. **                                                **
  14. ****************************************************
  15. ***************************************************/
  16.  
  17. #include "systems.h"
  18. #include "types.h"
  19. #include "errors.h"
  20. #include "atoms.h"
  21. #include "files.h"
  22. #include "maxvars.h"
  23.  
  24. /* 
  25.  
  26. [6]  READIN
  27. ReadIn reads a Prolog sentence from the current input file and builds a
  28. term from it.  The sentence is parsed using a shift- reduce parsing
  29. algorithm which depends on operator information in atom entries.
  30.  
  31. */
  32.  
  33.  
  34. IMPORT TERM A0,A1;
  35. IMPORT char CH,LASTCH;   /* from linebuffer.c */
  36. IMPORT void ABORT(),ERROR(),SYSTEMERROR(),SYNERROR();      
  37. IMPORT int ERRPOS;
  38. IMPORT boolean WARNFLAG;
  39. IMPORT ATOM LOOKUP(),LOOKATOM();
  40. IMPORT boolean In_Toplevel_Read;
  41. IMPORT TERM LISTREP();
  42. IMPORT boolean UNIFY();
  43. IMPORT boolean unget,ECHOFLAG;
  44. IMPORT int FirstCharPos;
  45. IMPORT void fillbuffer();
  46.  
  47. LOCAL boolean FILEENDED(void)
  48. {
  49. if(!unget && CHARPOS >=LINELENGTH && !ISTTY(inputfile))
  50.  fillbuffer();
  51. return (!unget && ISEOF(inputfile) && (CHARPOS >=LINELENGTH));
  52. }
  53.  
  54. /* Get the next character of the current input file in 'ch'. */
  55. /* inline-code in READIN */
  56. LOCAL void GETCHAR(void)
  57.   if(unget){unget=false; return;}
  58.   LASTCH=CH;
  59.   if(FILEENDED()){CH= '\n'; return; }
  60.   if( CHARPOS >=LINELENGTH ){
  61.      /* no char's in the buffer */
  62.      fillbuffer();
  63.      }
  64.   CH=LINEBUF[CHARPOS++] ;if(ECHOFLAG)wc(CH);
  65.   if(CH== '\n') {FirstCharPos=CHARPOS ; ERRPOS=0; LINENUMBER++;}
  66. }
  67.  
  68. LOCAL boolean LINEENDED(void)
  69. { if(CHARPOS >=LINELENGTH && !ISTTY(inputfile))
  70.  fillbuffer();
  71.   return (FILEENDED() || LINEBUF[CHARPOS]== '\n');
  72. }
  73.  
  74. LOCAL void REGET(void)
  75. { unget=true;
  76. }
  77.  
  78. #if !BIT8
  79. #define STRINGSPACE 256 /* Size of string buffer. */
  80. #endif
  81. #if BIT8
  82. #define STRINGSPACE 128 /* Size of string buffer. */
  83. #endif
  84.  
  85. LOCAL char ATOMTAB[STRINGSPACE+1]; /* also used in help.c */
  86.  
  87. LOCAL int ATOMINDEX;
  88.  
  89. LOCAL void ATOMCHAR (register char C)
  90. { if(ATOMINDEX>=STRINGSPACE) ERROR(aSTRINGSPACEE);
  91.   ATOMTAB[ATOMINDEX++]=C;
  92. }
  93.  
  94. /*
  95. EXPORT TERM READIN();
  96. EXPORT boolean DOREAD();
  97. EXPORT TERM VARTERM();
  98. EXPORT int VARCOUNT;
  99. EXPORT PREC LPREC(),RPREC();
  100. EXPORT CHARCLAS[];
  101. */
  102.  
  103. #if BIT32
  104. #define READSIZE 2000      /* Size of stack */
  105. #define READDEPTH 1000    /* Max. nesting depth */
  106. #endif
  107. #if BIT16
  108. #define READSIZE  250 
  109. #define READDEPTH 250
  110. #endif
  111. #if BIT8
  112. #define READSIZE 50
  113. #define READDEPTH 50
  114. #endif
  115.  
  116. #if BIT8
  117. #define VARLIMIT   100
  118. #endif
  119. #if BIT16
  120. #define VARLIMIT   200
  121. #endif
  122. #if BIT32
  123. #define VARLIMIT  2000
  124. #endif
  125.  
  126. #define RBRACE '}'
  127.  
  128. /* characters are classified as follows:
  129.    small letters  a..z:      SC 
  130.    large letters  A..Z_:   BC 
  131.    digits 0..9:              DC
  132.    spaces                    C0
  133.    atomic characters         OC
  134.    special characters ( ) ' " [ ] { }  |  , 
  135.    are coded by itself
  136.    and all other characters are coded as  0
  137. */
  138.  
  139. #define SC 1
  140. #define BC 2
  141. #define DC 3
  142. #define OC 4
  143. #define C0 5 
  144.  
  145. char CHARCLASS[256]=
  146.  
  147. /*      0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F */
  148. /*--------------------------------------------------------------------*/
  149. /*0*/ { C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0,
  150. /*1*/   C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0, C0,
  151. /*2*/   C0,'!','"', OC, SC, OC,OC,'\'','(',')', OC, OC,',', OC, OC, OC,
  152. /*3*/   DC, DC, DC, DC, DC, DC, DC, DC, DC, DC, OC, OC, OC, OC, OC, OC,
  153. /*4*/   OC, BC, BC, BC, BC, BC, BC, BC, BC, BC, BC, BC, BC, BC, BC, BC,
  154. /*5*/   BC, BC, BC, BC, BC, BC, BC, BC, BC, BC, BC,'[', OC,']', OC, BC,
  155. /*6*/   OC, SC, SC, SC, SC, SC, SC, SC, SC, SC, SC, SC, SC, SC, SC, SC,
  156. /*7*/   SC, SC, SC, SC, SC, SC, SC, SC, SC, SC, SC,'{','|','}','~', C0 };
  157.  
  158.  
  159. #define isdigit(CH)      (CHARCLASS[CH]==DC )
  160.  
  161. /* The precedence for a left operand of a. */
  162. GLOBAL PREC LPREC (ATOM A)
  163. { switch (oclass(A))
  164.   { case XFO:
  165.     case XFXO:
  166.     case XFYO:
  167.       return oprec(A)-1;
  168.     default:
  169.       return oprec(A);
  170.   }
  171. }
  172.  
  173. /* The precedence for a right operand of a. */
  174. GLOBAL PREC RPREC (ATOM A)
  175. { switch (oclass(A))
  176.   { case FXO:
  177.     case XFXO:
  178.     case YFXO:
  179.       return oprec(A)-1;
  180.     default:
  181.       return oprec(A);
  182.   }
  183. }
  184.  
  185. /*
  186.    Input and parse a Prolog sentence and build a term from it.  The
  187.    finite state part of the parser is characterized by the variables
  188.    'context' and 'expected'.
  189.    'context' indicates the construct being parsed:
  190.       outerK       The outermost level of a sentence.
  191.       innerK       An expression in parentheses.
  192.       funcK        The arguments of a functor.
  193.       listK        The elements of a list.
  194.       endlistK     A list continuation (between '|' or ',..'
  195.                    and ']' in a list).
  196.       curlyK       An expression in curly brackets.
  197.    'expected' indicates whether the next symbol is to be an operator
  198.    (opX) or an operand (randX).
  199.    Two stacks are used: one, represented by the array 'stack', to hold
  200.    parts of incompletely parsed terms, the other, represented by the
  201.    array 'statestack', to hold contextual information during parsing of
  202.    nested constructs. In fact, the parsing algorithm corresponds to a
  203.    stack machine with a single stack, but two stacks are used only as a
  204.    matter of convenience.
  205. */
  206.  
  207. #define OUTERK 0
  208. #define INNERK 1
  209. #define FUNCK 2
  210. #define LISTK 3
  211. #define ENDLISTK 4
  212. #define CURLYK 5
  213. #define STATE  int
  214.  
  215. #define TERML 0
  216. #define OPL 1
  217. #define FUNCL 2
  218. #define MARKL 3
  219. #define ELEMTAG int
  220.  
  221. LOCAL STATE  CONTEXT;
  222. LOCAL boolean OPEXPECTED; 
  223. LOCAL PREC  HIPREC, LOPREC;
  224. LOCAL int  RTOP;
  225.  
  226. LOCAL TERM TSTACK[READSIZE];
  227. LOCAL ATOM ASTACK[READSIZE];
  228. LOCAL ELEMTAG TAGSTACK[READSIZE];
  229.  
  230. LOCAL void RPOP(register ATOM *PA, register TERM *PT)
  231. { *PA=ASTACK[RTOP]; *PT=TSTACK[RTOP]; RTOP--; }
  232.  
  233. LOCAL void RPUSH (register ELEMTAG T, register ATOM A, register TERM X)
  234. { if(RTOP>=READSIZE) SYNERROR(READSTACKE);
  235.   RTOP++;
  236.   TAGSTACK[RTOP]=T; ASTACK[RTOP]=A; TSTACK[RTOP]=X;
  237. }
  238.  
  239. LOCAL  int STOP;
  240. LOCAL  int READCONTEXT[READDEPTH],
  241.             READPREC[READDEPTH];
  242.  
  243. LOCAL void SAVECONTEXT(void)
  244. { if(STOP>=READDEPTH) SYNERROR(READNESTE);
  245.   READCONTEXT[STOP]=CONTEXT; READPREC[STOP]=HIPREC; STOP++;
  246. }
  247.  
  248. LOCAL void RESTORECONTEXT(void)
  249. { STOP--; CONTEXT=READCONTEXT[STOP]; HIPREC=READPREC[STOP];
  250. }
  251.  
  252. int  VARCOUNT;
  253. /*
  254. LOCAL  struct 
  255.   { string aIDENT; 
  256.     TERM  ROOTVAR;
  257.      int counter;} VARTABLE[MAXVARS];
  258. */
  259. LOCAL string aIDENT[MAXVARS];
  260. /*LOCAL*/ TERM VAR_TAB[MAXVARS]; /* also used in write.c */
  261. LOCAL int counter[MAXVARS];
  262.  
  263. TERM VARTERM(void)
  264. { TERM Q,R; int I;
  265.   if(VARCOUNT==0) return nil_term;
  266.   R=nil_term;
  267.   for(I=VARCOUNT-1; 0<=I; I--)
  268.     { Q=mk2sons(LOOKUP(aIDENT[I],0,false),nil_term,
  269.                  VART,VAR_TAB[I]);
  270.       if(non_nil_term(R))  R=mkfunc(NL_2,mk2sons(ISEQ_2,Q,VART,R));
  271.       else R=mkfunc(ISEQ_2,Q);
  272.     }
  273.   if(non_nil_term(R))
  274.     { Q=mk2sons(WRITE_1,R,GOTO_1,
  275.                  mk2sons(NOT_1,mkfunc(ASK_1,mkint(59)),nil_atom,nil_term));
  276.       return Q;
  277.     }
  278.   return nil_term;
  279. }
  280.  
  281.  
  282. /*
  283.       Collapse items on the stack. Before each reduction step, the
  284.       operator a on top of the stack is "balanced" against the
  285.       precedences p=b@.oprec and lp=Lprec(b) of a new operator b,
  286.       to see if a could be a left operand of b, or b a right operand of
  287.       a. If neither is possible or both are possible, a precedence
  288.       conflict is reported.  If only the first is possible, a reduction
  289.       step is taken. If only the second is possible, reduction is
  290.       complete.
  291. */
  292.  
  293. LOCAL void REDUCE (PREC P, PREC LP)
  294. { TERM  X, Y;
  295.   ATOM  A,XA,YA;
  296.   RPOP(&XA,&X);
  297.   while(TAGSTACK[RTOP]==OPL)
  298.     { A=ASTACK[RTOP];
  299.       if(RPREC(A)>=P)
  300.         if(oprec(A)<=LP) SYNERROR(PRECE);
  301.         else break;
  302.       else
  303.         if(oprec(A)>LP) SYNERROR(PRECE);
  304.         else 
  305.         { RTOP--;
  306.           switch (oclass(A)) 
  307.           { case FXO:
  308.             case FYO:
  309.               X=mkfunc(XA,X); XA=A; 
  310.               break;
  311.             case XFXO:
  312.             case XFYO:
  313.             case YFXO:
  314.               RPOP(&YA,&Y); X=mk2sons(YA,Y,XA,X); XA=A; break;
  315.             case XFO:
  316.             case YFO:break;
  317.             case NONO: break;
  318.             default: SYSTEMERROR("REDUCE");
  319.           }
  320.         }
  321.     }
  322.   RPUSH(TERML,XA,X); 
  323. }
  324.  
  325. /*
  326.       Attempt to force the state required for a delimiter.
  327.       This state must satisfy the predicate
  328.          (expected=opX) and (context in s).
  329.       If initially (expected=randX) and the top item on the stack
  330.       is a prefix operator, this operator is converted to an atom.
  331.       This allows for constructions such as (?-) in which a prefix
  332.       operator occurs as an atom.
  333. */
  334.  
  335. LOCAL void CHECKDELIM (void)
  336. { ATOM  A; TERM X;
  337.   if(!OPEXPECTED)
  338.     { if(TAGSTACK[RTOP]!=OPL) SYNERROR(NEEDRANDE);
  339.       RPOP(&A,&X);
  340.       if(oclass(A)!=FXO && oclass(A)!=FYO) SYNERROR(NEEDRANDE);
  341.       RPUSH(TERML,LOOKATOM(A,0),nil_term); 
  342.     }
  343.   REDUCE(MAXPREC,MAXPREC);
  344. }
  345.  
  346. /* Process an atom. */
  347.  
  348. LOCAL void SQUASHRAND (ATOM A)
  349. { PREC  P, LP;
  350.   P=oprec(A);
  351.   LP=LPREC(A);
  352.   if(LP<LOPREC ||
  353.       (P>SUBPREC && 
  354.         CONTEXT!=OUTERK && CONTEXT!=INNERK && CONTEXT!=CURLYK))
  355.     SYNERROR(PRECE);
  356.   REDUCE(P,LP);
  357. }
  358.  
  359. /* Read an atom or string quoted by 'q' and store its characters
  360.       in the atom table, translating pairs of embedded quotes. */
  361.  
  362. LOCAL void SCANQUOTE (char Q)
  363.   ATOMINDEX=0; 
  364.   for(;;)
  365.   { 
  366.     if(CH==Q)
  367.       { GETCHAR(); if(CH!=Q) return; }
  368.     if(CH=='\\') 
  369.       { int suM; 
  370.  GETCHAR();
  371.  switch(CH)
  372.  { case 'n': CH='\n'; break;
  373.    case 'r': CH='\r'; break;
  374.    case 'b': CH='\b'; break;
  375.    case 't': CH='\t'; break;
  376.    case 'f': CH='\f'; break;
  377.    case 'v': CH='\v'; break;
  378.    case 'a': CH='\007';break;
  379.    case '\\': CH= '\\';break;
  380.    default:
  381.              if(CHARCLASS[CH]!=DC)break;
  382.              sum=CH - '0';
  383.              GETCHAR();
  384.              if(CHARCLASS[CH] !=DC)
  385.              {
  386.                  if(ATOMINDEX>=STRINGSPACE) ERROR(aSTRINGSPACEE);
  387.                  ATOMTAB[ATOMINDEX++]=sum;
  388.          continue;
  389.              }
  390.              sum=sum * 8 + CH - '0';
  391.              GETCHAR();
  392.              if(CHARCLASS[CH] !=DC)
  393.              {
  394.                  if(ATOMINDEX>=STRINGSPACE) ERROR(aSTRINGSPACEE);
  395.                  ATOMTAB[ATOMINDEX++]=sum;
  396.          continue;
  397.              }
  398.              sum=sum * 8 + CH - '0';
  399.              CH= (char)(sum & 0377);break;
  400.  
  401.  }
  402.       }
  403.     if(ATOMINDEX>=STRINGSPACE) ERROR(aSTRINGSPACEE);
  404.     ATOMTAB[ATOMINDEX++]=CH;
  405.     GETCHAR();
  406.   }
  407. }
  408.  
  409. /* Enter a variable and return it as a term. */
  410.  
  411. /* variable handling */
  412.  
  413. LOCAL int VARHWM;
  414. LOCAL TERM ENTERVAR (void)
  415. { TERM  V;
  416.   int  N=0,NEWINDEX;
  417. static char vtab[VARLIMIT];
  418.   string NEWVAR;
  419.   NEWVAR= &vtab[VARHWM]; NEWINDEX=VARHWM;
  420.   vtab[NEWINDEX++]=LASTCH;
  421.   while(SC<=CHARCLASS[CH] && CHARCLASS[CH]<=DC)
  422.     { if(NEWINDEX>=VARLIMIT) ABORT(VARSPACEE);
  423.       vtab[NEWINDEX++]=CH;
  424.       GETCHAR(); 
  425.     }
  426.   vtab[NEWINDEX++]=0;
  427.   while(N!=VARCOUNT)
  428.   { N++;
  429.     if(strcmp(aIDENT[N-1],NEWVAR)==0){
  430.       counter[N-1]++;
  431.       return VAR_TAB[N-1];}
  432.   }
  433.   if(VARCOUNT>=MAXVARS) SYNERROR(NVARSE);
  434.   VARCOUNT++;
  435.   VARHWM=NEWINDEX;  
  436.   V=mkfreevar();
  437.   aIDENT[VARCOUNT-1]=NEWVAR;
  438.   VAR_TAB[VARCOUNT-1]=V;
  439.   counter[VARCOUNT-1]=1;
  440.   return V;
  441. }
  442.  
  443. LOCAL void Var_Check(void)
  444. { int i;
  445.   /* check if a variable is only used only at one time */
  446.   for(i=0;i<VARCOUNT;i++)
  447.     if(counter[i]==1)
  448.       { ws("WARNING: "); ws(aIDENT[i]); ws(" used only once ! \n"); }
  449. }
  450.  
  451. #if REALARITH
  452. LOCAL REAL genreal(REAL r, int expo)
  453. {while(expo >=10 ) {expo-=10; r *=1e10;}
  454.  while(expo >=1){ expo-- ; r *=10.0; }
  455.  while(expo <= -10 ){expo +=10; r *=1e-10;}
  456.  while(expo <= -1) { expo ++ ; r *=0.1;}
  457.  return r;
  458. }
  459. #endif
  460.  
  461. #if REALARITH && LONGARITH
  462. LOCAL TERM readnumber(boolean sign)
  463. {LONG l ; int  i ; REAL r ;
  464.  boolean esign=false;
  465.  int expo=0;
  466.  l= (LONG)(i=LASTCH-'0');
  467.  r= (REAL)i;
  468.  while(isdigit(CH)){
  469.  l=l * 10l  + (LONG)(CH -'0');
  470.  i=i * 10   + (CH -'0');
  471.  r=r * 10.0 + (REAL)(CH -'0');
  472.  GETCHAR();
  473.  }
  474.   GETCHAR();
  475.   if(LASTCH== '.' && isdigit(CH))goto double1;
  476.   if((LASTCH== 'e' || LASTCH== 'E') &&
  477.      (isdigit(CH)||CH== '+'||CH=='-'))goto double2;
  478.   /* a normal integer */
  479.   REGET();
  480.   if( l <=  r-0.5) {
  481.  /* converting integer to real */
  482.  if(WARNFLAG)ws("WARNING: converting integer to real\n");
  483.  return mkreal(sign ? -r : r);
  484.  }
  485.   if(i==l){
  486.  /* a normal integer */
  487.  return mkint(sign ? -i : i);
  488.  }
  489.   else {
  490.  /* a long integer */
  491.         return mklong(sign ? -l : l);
  492.  }
  493. double1:
  494.   expo=0;
  495.   while(isdigit(CH)){
  496.  expo--;
  497.  r=r * 10.0 + (REAL)(CH - '0');
  498.  GETCHAR();
  499.         }
  500.   r=genreal(r,expo);
  501.   GETCHAR();
  502.   if((LASTCH== 'e' || LASTCH== 'E')&
  503.      (isdigit(CH)||CH== '+'||CH=='-'))goto double2;
  504.   REGET();
  505.   return mkreal( sign ? -r : r);
  506. double2:
  507.   /* scanning the exponent */
  508.   /* exponent starts with CH */
  509.   switch (CH){
  510.  case '-' : esign=true;
  511.  case '+' : GETCHAR();
  512.  }
  513.   expo=0; /* no exponent=> exponent=0 */
  514.   while(isdigit(CH)){
  515.  if(expo < 1000 )expo=expo * 10 + (CH - '0');
  516.  GETCHAR();
  517.  }
  518.   r=genreal(r, esign ? -expo : expo);
  519.   return mkreal(sign ? -r : r);
  520. }
  521. #endif
  522.  
  523. #if ! REALARITH && LONGARITH
  524. LOCAL TERM readnumber(boolean sign)
  525. {
  526.   LONG l ; int  i ;
  527.   l= (LONG)(i=LASTCH-'0');
  528.  while(isdigit(CH))
  529.       {
  530.           l=l * 10l  + (LONG)(CH -'0');
  531.           i=i * 10   + (CH -'0');
  532.           GETCHAR();
  533.        }
  534.   if(i==l) return mkint(sign ? -i : i);
  535.   else  return mklong(sign ? -l : l);
  536. }
  537. #endif
  538.  
  539. #if ! REALARITH && !LONGARITH
  540. LOCAL TERM readnumber(boolean sign)
  541. {
  542.   int  i ;
  543.   i=LASTCH-'0';
  544.   while(isdigit(CH))
  545.       {
  546.           i=i * 10   + (CH -'0');
  547.           GETCHAR();
  548.        }
  549.  return mkint(sign ? -i : i);
  550. }
  551. #endif
  552.  
  553. #if REALARITH && !LONGARITH
  554. LOCAL TERM readnumber(boolean sign)
  555. {int  i ; REAL r ;
  556.  boolean esign=false;
  557.  int expo=0;
  558.  i=LASTCH-'0';
  559.  r= (REAL)i;
  560.  while(isdigit(CH)){
  561.  i=i * 10   + (CH -'0');
  562.  r=r * 10.0 + (REAL)(CH -'0');
  563.  GETCHAR();
  564.  }
  565.   GETCHAR();
  566.   if(LASTCH== '.' && isdigit(CH))goto double1;
  567.   if((LASTCH== 'e' || LASTCH== 'E') &&
  568.      (isdigit(CH)||CH== '+'||CH=='-'))goto double2;
  569.   /* a normal integer */
  570.   REGET();
  571.   if( i <=  r-0.5) {
  572.  /* converting integer to real */
  573.  if(WARNFLAG)ws("WARNING: converting integer to real\n");
  574.  return mkreal(sign ? -r : r);
  575.  }
  576.  /* a normal integer */
  577.  return mkint(sign ? -i : i);
  578. double1:
  579.   expo=0;
  580.   while(isdigit(CH)){
  581.  expo--;
  582.  r=r * 10.0 + (REAL)(CH - '0');
  583.  GETCHAR();
  584.         }
  585.   r=genreal(r,expo);
  586.   GETCHAR();
  587.   if((LASTCH== 'e' || LASTCH== 'E') &&
  588.      (isdigit(CH)||CH== '+'||CH=='-'))goto double2;
  589.   REGET();
  590.   return mkreal( sign ? -r : r);
  591. double2:
  592.   /* scanning the exponent */
  593.   /* exponent starts with CH */
  594.   switch (CH){
  595.  case '-' : esign=true;
  596.  case '+' : GETCHAR();
  597.  }
  598.   expo=0; /* no exponent=> exponent=0 */
  599.   while(isdigit(CH)){
  600.  if(expo < 1000 )expo=expo * 10 + (CH - '0');
  601.  GETCHAR();
  602.  }
  603.   r=genreal(r, esign ? -expo : expo);
  604.   return mkreal(sign ? -r : r);
  605. }
  606. #endif
  607.  
  608. TERM READIN (void)
  609. { TERM T, X; 
  610.   ATOM A,HA,TA,XA; 
  611.   int N,TTOP; 
  612.   STATE K; PREC H;
  613.   boolean atom_is_quoted=false;
  614.  
  615.   RTOP=0;
  616.   STOP=0;
  617.   VARHWM=0;  
  618.   VARCOUNT=0;
  619.   RPUSH(MARKL,nil_atom,nil_term);
  620.   CONTEXT=OUTERK;
  621.   OPEXPECTED=false;
  622.   HIPREC=MAXPREC;
  623.   GETCHAR(); /* next char is CH */
  624.   for(;;)
  625.   { if(FILEENDED())
  626.     { if(RTOP <=1) return mkatom(END_0);
  627.        /* End of file - represented by  end. */
  628.       goto fullstop;
  629.     }
  630.     atom_is_quoted=false;
  631.     ERRPOS=CHARPOS;
  632.     GETCHAR();
  633.     switch (CHARCLASS[LASTCH]) 
  634.     { case SC:
  635.         ATOMINDEX=0; 
  636.         ATOMTAB[ATOMINDEX++]=LASTCH;
  637.         while( SC<=CHARCLASS[CH] && CHARCLASS[CH]<=DC )
  638.           { if(ATOMINDEX>=STRINGSPACE) ERROR(aSTRINGSPACEE);
  639.             ATOMTAB[ATOMINDEX++]=CH;
  640.         GETCHAR(); 
  641.       }
  642.         goto new_atom;
  643.       
  644.       case '\'':
  645.         SCANQUOTE('\''); atom_is_quoted=true;
  646.         goto new_atom;
  647.  
  648.       case '"':
  649.         SCANQUOTE('"');
  650.         ATOMTAB[ATOMINDEX++]=0;
  651.         T=LISTREP(ATOMTAB); TA=name(T); T=son(T); goto shift;
  652.  
  653.       case OC:
  654.         if(LASTCH=='/' && CH=='*')
  655.           /* A comment. Comments don't nest. */
  656.           { 
  657.             GETCHAR();
  658.             do {GETCHAR();if(FILEENDED())ERROR(COMMENTE);}
  659.             while(LASTCH!='*' || CH!='/');
  660.             GETCHAR();;
  661.             continue;
  662.           }
  663.  
  664.         if(LASTCH== '%')
  665.          /* also a comment */
  666.          { if(CH != '\n')
  667.              while(!LINEENDED()) GETCHAR();
  668.            GETCHAR();
  669.            continue;
  670.          }
  671.  
  672.         if(LASTCH=='-' && CHARCLASS[CH]==DC && !OPEXPECTED)
  673.           /* A negative number. */
  674.           { GETCHAR(); 
  675.             T=readnumber(true); TA=VART; goto shift; }
  676.  
  677.         if(LASTCH=='.' && CHARCLASS[CH]==C0)
  678.           /* A full stop. */
  679.           { 
  680.            fullstop:
  681. #if CPM
  682.         if(CH==13) GETCHAR();
  683. #endif
  684.         CHECKDELIM();
  685.             if(CONTEXT!=OUTERK) SYNERROR(BADDOTE);
  686.             if(WARNFLAG && !In_Toplevel_Read)Var_Check();
  687.             RPOP(&TA,&T); return mkfunc(TA,T);
  688.           }
  689.  
  690.         ATOMINDEX=0; 
  691.         ATOMTAB[ATOMINDEX++]=LASTCH;
  692.         while(CHARCLASS[CH]==OC)
  693.           { if(ATOMINDEX>=STRINGSPACE) ERROR(aSTRINGSPACEE);
  694.             ATOMTAB[ATOMINDEX++]=CH;
  695.         GETCHAR(); 
  696.       }
  697.         goto new_atom;
  698.  
  699.       case BC:
  700.         /* An anonymous able: replaced by a unique ordinary able. */
  701.         if(LASTCH=='_' && (CHARCLASS[CH]>DC || CHARCLASS[CH]==0))
  702.          { TA=UNBOUNDT; T=nil_term; goto shift; }
  703.  
  704.         /* ordinary variables */
  705.         T=ENTERVAR(); TA=VART; goto shift;
  706.  
  707.       case DC:
  708.         /* positiv numbers */
  709.         T=readnumber(false); TA=VART; goto shift;
  710.  
  711.  
  712.       case '(':
  713.         K=INNERK; H=MAXPREC; goto enter;
  714.  
  715.       case ')':
  716.         CHECKDELIM();
  717.         switch (CONTEXT) 
  718.         { case INNERK:
  719.             RPOP(&TA,&T); goto exit;
  720.           case FUNCK:   
  721.             /* assemble a function call */
  722.             TTOP=RTOP--;
  723.             for(N=1; TAGSTACK[RTOP]==TERML; RTOP--) N++;
  724.             RTOP=TTOP;
  725.             X=stackterms(N); TTOP=N;
  726.             while(N-->0)
  727.               { TERM ARGS; ATOM ARGA;
  728.                 RPOP(&ARGA,&ARGS);
  729.                 name(X+term_units(N))=ARGA; son(X+term_units(N))=ARGS; 
  730.               }
  731.             T=X; TA=LOOKATOM(ASTACK[RTOP],TTOP);
  732.             goto exit;
  733.           default:
  734.             SYNERROR(BADKETE);
  735.         }
  736.  
  737.       case '!':
  738.          A=CUT_0;goto get_atom;
  739.  
  740.       case '~':
  741. #if SYMBOLARITH
  742.          A=TILDE_0;goto get_atom;
  743. #endif
  744. #if !SYMBOLARITH
  745.          ATOMINDEX=0;
  746.          ATOMTAB[ATOMINDEX++]='~';
  747.      goto new_atom;
  748. #endif
  749.  
  750.       case '[':
  751.         while(CHARCLASS[CH]==C0 && !FILEENDED())GETCHAR();
  752.         if(CH==']') /* The empty list []. */
  753.           { GETCHAR(); A=NIL_0; goto get_atom; } 
  754.         
  755.         K=LISTK; H=SUBPREC; goto enter;
  756.  
  757.       case ']':
  758.         CHECKDELIM();
  759.         if(CONTEXT==LISTK) 
  760.           RPUSH(TERML,NIL_0,nil_term); 
  761.         else if(CONTEXT!=ENDLISTK) 
  762.           SYNERROR(BADKETE);
  763.         /* assemble a list */
  764.         RPOP( &TA, &T); 
  765.         do { RPOP( &XA, &X); T=mk2sons(XA,X,TA,T); TA=CONS_2; }
  766.         while(TAGSTACK[RTOP]==TERML);
  767.         goto exit;
  768.  
  769.       case '{':
  770.  while(CHARCLASS[CH]==C0 && !FILEENDED())GETCHAR();
  771.         if(CH==RBRACE) /* The 'curly' atom. */
  772.           { GETCHAR(); A=CURLY_0; goto get_atom; }
  773.         
  774.         K=CURLYK; H=MAXPREC; goto enter;
  775.  
  776.       case '}':
  777.         CHECKDELIM();
  778.         if(CONTEXT!=CURLYK) SYNERROR(BADKETE);
  779.         RPOP(&TA,&T); T=mkfunc(TA,T); TA=CURLY_1; goto exit;
  780.  
  781.       case ',':
  782.         switch(CONTEXT)
  783.         { case OUTERK: case INNERK: case CURLYK:
  784.             A=COMMA_2; goto get_atom;
  785.           case FUNCK: case LISTK:
  786.             CHECKDELIM();
  787.             OPEXPECTED=false;
  788.             HIPREC=SUBPREC;
  789.             continue;
  790.           default:
  791.             SYNERROR(BADCDDE);
  792.         }
  793.       
  794.  
  795.       case '|':
  796.         CHECKDELIM();
  797.         if(CONTEXT!=LISTK) SYNERROR(BADCDDE);
  798.         CONTEXT=ENDLISTK;
  799.         OPEXPECTED=false;
  800.         HIPREC=SUBPREC;
  801.         continue;
  802.  
  803.       case C0:
  804.         continue;
  805.  
  806.       default:
  807.         SYNERROR(WIERDCHE);
  808.     }
  809.     /* semantic actions */
  810.     new_atom:
  811.       ATOMTAB[ATOMINDEX++]=0;
  812.       A=LOOKUP(ATOMTAB,0,false);
  813.     get_atom:
  814.       if(!OPEXPECTED)
  815.       { 
  816.         if(CH=='(') /* functor in standard notation. */
  817.         { GETCHAR(); RPUSH(FUNCL,A,nil_term); 
  818.           K=FUNCK; H=SUBPREC; 
  819.           goto enterfunc;
  820.         }
  821.         if(atom_is_quoted) goto quot_atom;
  822.         HA=LOOKATOM(A,-1);
  823.         if(oclass(HA)==FXO || oclass(HA)==FYO)
  824.         { A=HA;
  825.           if(oprec(A)>HIPREC) SYNERROR(PRECE);
  826.           RPUSH(OPL,A,nil_term); 
  827.           OPEXPECTED=false; HIPREC=RPREC(A);
  828.           continue;
  829.         }
  830.         /* An atom, i.e. a functor of tarity 0. */
  831.      quot_atom:
  832.           A=LOOKATOM(A,0);
  833.           RPUSH(TERML,A,nil_term); 
  834.           OPEXPECTED=true; LOPREC=0;
  835.           continue;
  836.         }
  837.  /* OPEXPECTED ! */
  838.         if(atom_is_quoted) SYNERROR(NEEDOPE);
  839.         HA=LOOKATOM(A,-1);
  840.         if(oclass(HA)==XFO || oclass(HA)==YFO)
  841.         {  TERM Y; ATOM YA;
  842.            A=HA;
  843.            SQUASHRAND(A);
  844.            RPOP(&YA,&Y);
  845.            Y=mkfunc(YA,Y); 
  846.            RPUSH(TERML,A,Y); 
  847.            OPEXPECTED=true; LOPREC=oprec(A);
  848.            continue;
  849.         }
  850.          HA=LOOKATOM(A,-2);
  851.          if(oclass(HA)==XFXO || oclass(HA)==XFYO || oclass(HA)==YFXO)
  852.          {  A=HA;
  853.             SQUASHRAND(A);
  854.             RPUSH(OPL,A,nil_term); 
  855.             OPEXPECTED=false; HIPREC=RPREC(A);
  856.             continue;
  857.          }
  858.      else  
  859.             SYNERROR(NEEDOPE);
  860.  
  861.     shift:
  862.       if(OPEXPECTED) SYNERROR(NEEDOPE);
  863.       RPUSH(TERML,TA,T); 
  864.       OPEXPECTED=true;
  865.       LOPREC=0;
  866.       continue;
  867.     enter:
  868.       if(OPEXPECTED) SYNERROR(NEEDOPE);
  869.       RPUSH(MARKL,nil_atom,nil_term);
  870.     enterfunc: /* also called for call in standard syntax */
  871.       SAVECONTEXT();
  872.       CONTEXT=K;
  873.       OPEXPECTED=false;
  874.       HIPREC=H;
  875.       continue;
  876.     exit:
  877.       RTOP--; RPUSH(TERML,TA,T);
  878.       RESTORECONTEXT();
  879.       OPEXPECTED=true;
  880.       LOPREC=0;
  881.       continue;
  882.   }
  883.   /* ReadIn */
  884. }
  885.  
  886.  
  887. GLOBAL boolean DOREAD(void)
  888. /* read/2 */
  889. {
  890.     TERM T,TT,Q;
  891.     int i;
  892.  
  893.     if(!UNI(A0,READIN())) return false;
  894.     TT=T=mkatom(CONS_2);
  895.     for(i=0; i < VARCOUNT  ; ++i)
  896.     {
  897.         Q=mk2sons(LOOKUP(aIDENT[i],0,false),nil_term,VART,VAR_TAB[i]);
  898.         son(T)=mk2sons(ISEQ_2,Q,CONS_2,nil_term);
  899.         T=br(son(T));
  900.     }
  901.     name(T)=NIL_0;
  902.     son(T)=nil_term;
  903.     return UNI(TT,A1);
  904. }
  905.  
  906.  
  907.